//
// Created by root on 5/1/17.
//

#include <string.h>
#include "runner_ds.h"

#define HIERARCHY  " -Object\n\
 --oop/graph/Shape\n\
 ---oop/graph/Rectangle\n\
 ---oop/graph/Circle\n\
 --oop/poly/Animal\n\
 ---oop/poly/Chicken\n\
 ---oop/poly/Duck"

#define assert_tree_path1(t,n1)     node = tree_find(t, n1); \
    assert_non_null(node); \
    assert_string_equal(node->name, n1); \
    assert_null(node->parent);

#define assert_tree_path2(t,n1,n2)  node = tree_find(t, n2); \
    assert_non_null(node); \
    assert_string_equal(node->name, n2); \
    assert_non_null(node->parent); \
    assert_string_equal(node->parent->name, n1); \
    assert_null(node->parent->parent);

#define assert_tree_path3(t,n1,n2,n3)   node = tree_find(t, n3); \
    assert_non_null(node); \
    assert_string_equal(node->name, n3); \
    assert_non_null(node->parent); \
    assert_string_equal(node->parent->name, n2); \
    assert_non_null(node->parent->parent); \
    assert_string_equal(node->parent->parent->name, n1); \
    assert_null(node->parent->parent->parent);


static void test_alloc_tree() {
    Tree *tree = alloc_tree();
    assert_non_null(tree);
}

static void test_alloc_tree_node() {
    TreeNode *treeNode = alloc_tree_node();
    assert_non_null(treeNode);
    assert_null(treeNode->name);
    assert_null(treeNode->data);
    assert_null(treeNode->parent);
    assert_non_null(treeNode->children);
}

static void test_init_tree() {
    Tree *tree = init_tree();
    assert_non_null(tree);
    assert_non_null(tree->root);
}

static void test_tree_add() {
    Tree *tree = init_tree();
    tree_add(tree, NULL, NULL, NULL);
    tree_add(tree, "abc", NULL, NULL);
    tree_add(tree, NULL, "Object", NULL);
    tree_add(tree, "Object", "PrimitiveObject", NULL);
    tree_add(tree, "PrimitiveObject", "Object", NULL);
}

static void test_tree_find() {
    Tree *tree = init_tree();
    tree_add(tree, NULL, "Object", NULL);
    tree_add(tree, "Object", "PrimitiveObject", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveBoolean", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveInteger", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveDouble", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveCharacter", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveString", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveSymbol", NULL);
    tree_add(tree, "PrimitiveObject", "PrimitiveProcedure", NULL);
    tree_add(tree, "Object", "Number", NULL);
    tree_add(tree, "Number", "Integer", NULL);
    tree_add(tree, "Number", "Double", NULL);

    TreeNode *node = NULL;
    assert_tree_path1(tree, "Object");
    assert_tree_path2(tree, "Object", "PrimitiveObject");
    assert_tree_path3(tree, "Object", "PrimitiveObject", "PrimitiveString");
    assert_tree_path3(tree, "Object", "Number", "Double");
}

/*
static void test_construct_tree() {
    Tree* tree = construct_tree(init_tree(), HIERARCHY, '-');

    TreeNode *node = NULL;
    assert_tree_path1(tree, "Object");
    assert_tree_path2(tree, "Object", "oop/graph/Shape");
    assert_tree_path3(tree, "Object", "oop/graph/Shape", "oop/graph/Rectangle");
    assert_tree_path3(tree, "Object", "oop/graph/Shape", "oop/graph/Circle");
    assert_tree_path2(tree, "Object", "oop/poly/Animal");
    assert_tree_path3(tree, "Object", "oop/poly/Animal", "oop/poly/Chicken");
    assert_tree_path3(tree, "Object", "oop/poly/Animal", "oop/poly/Duck");
}
*/

int main(int argc, char **argv) {
    const struct CMUnitTest tests[] = {
            cmocka_unit_test(test_alloc_tree),
            cmocka_unit_test(test_alloc_tree_node),
            cmocka_unit_test(test_init_tree),
            cmocka_unit_test(test_tree_add),
            cmocka_unit_test(test_tree_find),
            //cmocka_unit_test(test_construct_tree),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}
